package com.mf.all.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mf.all.entity.dto.TaskBo;
import com.mf.all.entity.dto.TaskDetailBo;
import com.mf.all.service.ITaskDetailService;
import com.mf.all.service.ITaskNotificationService;
import com.mf.all.utils.MailUtil;
import com.mf.all.emuns.TaskNotificationEnum;
import com.mf.all.emuns.TaskStatusEnum;
import com.mf.all.entity.dto.TaskNotificationBo;
import com.mf.all.mapper.TaskNotificationMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;

/**
 * 任务通知表 服务实现类
 *
 * @author mf
 * @since 2025-03-08
 */
@Service
@Slf4j
public class TaskNotificationServiceImpl extends ServiceImpl<TaskNotificationMapper, TaskNotificationBo> implements ITaskNotificationService {
    @Resource
    private MailUtil mailUtil;
    @Resource
    private ITaskDetailService taskDetailService;

    /**
     * 根据任务id删除没有通知的任务通知
     */

    @Override
    @Transactional
    public void deleteByTaskId(Integer taskId) {
        LambdaQueryWrapper<TaskNotificationBo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskNotificationBo::getTaskId, taskId)
                .eq(TaskNotificationBo::getStatus, TaskNotificationEnum.UN_NOTIFICATION.getCode());
        baseMapper.delete(wrapper);
    }

    @Override
    @Transactional
    public void setDayNotification(LocalDate date, List<TaskBo> taskBoList) {
        LambdaQueryWrapper<TaskNotificationBo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskNotificationBo::getNotificationDate, date);
        // 删除当天通知，在重新添加
        baseMapper.delete(wrapper);
        for (TaskBo taskBo : taskBoList) {
            // 只添加子任务通知
            if (taskBo.getSonCount() == 0) {
                // 设置通知时间 = 当前日期 + 汇报时间 + 延迟通知分钟
                TaskNotificationBo notificationBo = new TaskNotificationBo();
                LocalDateTime notificationTime = getNotificationTime(date, taskBo);
                // 已经过了通知时间的不进行通知 跳过
                if (LocalDateTime.now().isAfter(notificationTime)) {
                    continue;
                }

                notificationBo.setNotificationTime(notificationTime);
                notificationBo.setTaskId(taskBo.getId());
                notificationBo.setNotificationDate(date);
                notificationBo.setTaskName(taskBo.getTaskName());
                baseMapper.insert(notificationBo);
            }

        }
    }

    private static LocalDateTime getNotificationTime(LocalDate date, TaskBo taskBo) {
        final LocalTime reportTime = taskBo.getReportTime();
        final LocalTime motifTime = reportTime.plusMinutes(taskBo.getDelayNotificationMinute());
        return date.atTime(motifTime);
    }

    /**
     * 发送通知
     */
    @Override
    public void sendNotification() {
        log.info("开始发送任务通知");
        final LambdaQueryWrapper<TaskNotificationBo> wrapper = new LambdaQueryWrapper<>();

        // 通知时间小于当前时间并且状态为未通知进行通知
        wrapper.eq(TaskNotificationBo::getStatus, TaskNotificationEnum.UN_NOTIFICATION.getCode())
                .lt(TaskNotificationBo::getNotificationTime, LocalDateTime.now());
        List<TaskNotificationBo> notificationBoList = baseMapper.selectList(wrapper);

        notificationBoList.forEach(taskNotificationBo -> {
            final List<TaskDetailBo> list =
                    taskDetailService.findByTaskIdAndNotificationDate(taskNotificationBo.getTaskId(), LocalDate.now());
            log.info("任务通知:{}", list);
            if (list.isEmpty()) {
                log.info("任务通知" + taskNotificationBo.getTaskId() + "请添加任务汇报");
                mailUtil.sendEmail("任务通知:" + taskNotificationBo.getTaskName() + "请添加任务汇报", "请对当前任务进行汇报");
            }
            if (taskNotificationBo.getStatus().intValue() == TaskNotificationEnum.UN_NOTIFICATION.getCode()) {
                taskNotificationBo.setStatus(TaskNotificationEnum.NOTIFIED.getCode());
                baseMapper.updateById(taskNotificationBo);
            }

        });
    }

    /**
     * 设置任务通知
     */
    @Override
    @Transactional
    public void setTaskNotification(TaskBo taskBo) {
        final LocalDate planEnd = taskBo.getPlanEnd();
        final LocalDate localDate = LocalDate.now();
        // 查询通知表中是否有通知
        TaskNotificationBo notificationBo = findByTaskIdAndNotificationDate(taskBo.getId(), localDate);
        // 如果状态是进行中，那么要确定下通知表中的通知是否需要添加
        if (TaskStatusEnum.IN_PROGRESS.getCode().equals(taskBo.getStatus().intValue())) {
            // 设置通知时间 = 当前日期 + 汇报时间 + 延迟通知分钟
            final LocalDateTime notificationTime = getNotificationTime(localDate, taskBo);


            // 如果计划结束时间大于当前时间，并且通知时间在当前时间之后 那么就要通知
            if ((planEnd.isAfter(localDate) || planEnd.isEqual(localDate)) && notificationTime.isAfter(LocalDateTime.now())) {
                final TaskNotificationBo notificationBo1 = new TaskNotificationBo();
                // 没有那么设置通知任务
                if (notificationBo == null) {
                    notificationBo = notificationBo1;
                    notificationBo.setTaskId(taskBo.getId());
                    notificationBo.setNotificationDate(localDate);
                    notificationBo.setNotificationTime(notificationTime);
                    notificationBo.setTaskName(taskBo.getTaskName());
                    baseMapper.insert(notificationBo);
                } else {
                    // 如果有修改通知时间那么同步通知时间
                    if (!notificationBo.getNotificationTime().equals(notificationTime)) {
                        notificationBo.setNotificationTime(notificationTime);
                    }

                    notificationBo.setStatus(TaskNotificationEnum.UN_NOTIFICATION.getCode());

                    baseMapper.updateById(notificationBo);
                }
            } else {
                // 如果当前结束时间在计划结束时间之前，那么就要删除通知
                if (notificationBo != null) {
                    // 如果有通知，那么就要删除通知
                    if (TaskNotificationEnum.UN_NOTIFICATION.getCode().equals(notificationBo.getStatus())) {
                        notificationBo.setStatus(TaskNotificationEnum.CANCELLED.getCode());
                        baseMapper.updateById(notificationBo);
                    }
                }
            }

        } else if (notificationBo != null) {
            // 任务没有进行那么需要把通知取消掉，，并且还有通知消息
            if (TaskNotificationEnum.UN_NOTIFICATION.getCode().equals(notificationBo.getStatus())) {
                notificationBo.setStatus(TaskNotificationEnum.CANCELLED.getCode());
                baseMapper.updateById(notificationBo);
            }
        }
    }

    @Override
    @Transactional
    public TaskNotificationBo findByTaskIdAndNotificationDate(Integer taskId, LocalDate notificationDate) {
        final LambdaQueryWrapper<TaskNotificationBo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskNotificationBo::getTaskId, taskId).eq(TaskNotificationBo::getNotificationDate, notificationDate);
        return baseMapper.selectOne(wrapper);
    }

}
